/**
 * @FileName: ExportBroadbandTextData.java
 * @Author
 * @Description:
 * @Date 2016年4月13日 下午3:22:16
 * @CopyRight ZTE Corporation
 */
package cn.hpclub.server.service.ds;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.Prop;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

import cn.hpclub.server.model.SyncData;
import cn.hpclub.server.service.ds.DateUtils.SyncParams;
import cn.hpclub.server.util.ObjectUtil;

public class ExportBusinessCountTextData extends ExportTextDataService{

    private static final String FILE_NAME_PREFIX = "dzgyw";
    private static final String PATH_DS_YEWU     = "YeWuBanLi/";
    private static final Logger logger           = LoggerFactory.getLogger(ExportBusinessCountTextData.class);

    public ExportBusinessCountTextData(SyncParams params){
        this.params = params;
        Prop prop = DsPropKit.getProp();
        this.ftpParam = new FtpParam(prop.get("dzgywblHost"), prop.getInt("dzgywblServerPort"),
                prop.get("dzgywblUserName"), prop.get("dzgywblPassword"), prop.get("dzgywblEncoding"),
                prop.get("dzgywblRemotePath"));
    }

    @Override
    String getSql(SyncParams params){
        return null;
    }

    @Override
    String getFileName(SyncParams params){
        return String.format("%s%s%s", FILE_NAME_PREFIX, Integer.parseInt(params.tag) + 1, FILE_EXTENSION);
    }

    @Override
    String getFilePath(String fileName){
        SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM");
        String monthDirName = dateFormater.format(new Date());
        String dirPath = Common.getRootDir() + PATH_DS_YEWU + monthDirName;
        Common.checkDir(dirPath);
        return dirPath + "/" + fileName;
    }

    @Override
    String convertRecordToString(Record item){
        String[] columns = { "DisplayName", "user_name", "total_count" };
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < columns.length; i++){
            Object object = item.get(columns[i]);
            String value = object == null ? "" : object.toString().replace("\n", "").replace("\r", "");
            sb.append(value);
            if(i != (columns.length - 1)){
                sb.append("$");
            }
        }
        return sb.toString();
    }

    @Override
    void saveExportResult(SyncParams params, String filePath){
        String digest = DigestUtils.md5Hex(filePath);
        SyncData.dao.saveSyncData(params.tag, filePath, digest, getFileName(params));
    }

    private ConcurrentHashMap<String, String> getSearchInfo(SyncParams params){
        ConcurrentHashMap<String, String> searchMap = new ConcurrentHashMap<String, String>();
        searchMap.put("start", params.start);
        searchMap.put("end", params.end);
        return searchMap;
    }

    private String exportDataByParams(SyncParams params) throws IOException{
        ConcurrentHashMap<String, String> searchInfo = getSearchInfo(params);
        List<String> unique_business_code = new ArrayList<>();
        unique_business_code.add("ACAZ25477");
        unique_business_code.add("ACAZ25128");
        unique_business_code.add("ACAZ22308");
        unique_business_code.add("ACAZ22310");
        unique_business_code.add("ACAZ25126");
        unique_business_code.add("ACAZ25129");
        unique_business_code.add("ACAZ22309");
        unique_business_code.add("ACAZ22311");
        String sql_unique_sales = getSalesUniqueSql(searchInfo, unique_business_code);
        String sql_other_sales = getSalesOtherSql(searchInfo, unique_business_code);
        String sql_reservation = getReservationSql(searchInfo);
        OutputStreamWriter osr = null;
        try{
            String filePath = getFilePath(getFileName(params));
            osr = new OutputStreamWriter(new FileOutputStream(new File(filePath)), "gb2312");
            List<Record> unique_sales_list = Db.find(sql_unique_sales);
            List<Record> other_sales_list = Db.find(sql_other_sales);
            List<Record> reservation_list = Db.find(sql_reservation);
            unique_sales_list.addAll(other_sales_list);
            unique_sales_list.addAll(reservation_list);

            Map<String, Record> map = new HashMap<>();
            for(Record record : unique_sales_list){
                if(ObjectUtil.isEmpty(record.get("userId"))){
                    logger.error("one of record data error,the userId is null,source data is "
                            + JSONObject.toJSONString(record));
                    continue;
                }
                String userId = record.get("userId").toString();
                if(map.containsKey(userId)){
                    Record existRecord = map.get(userId);
                    record.set("total_count", record.getLong("total_count") + existRecord.getLong("total_count"));
                }
                map.put(userId, record);
            }
            List<Record> list = new ArrayList<>();
            for(String key : map.keySet()){
                Record obj = map.get(key);
                list.add(obj);
            }
            long s1 = System.currentTimeMillis();
            list = compilable(list);// 选择排序
            long s2 = System.currentTimeMillis();
            System.out.println("----------排序耗时：" + (s2 - s1) / 1000 + " 秒，共：" + list.size() + "条数据");
            outputToFile(list, osr);
            return filePath;
        }
        finally{
            closeWriter(osr);
        }
    }

    private List<Record> compilable(List<Record> list){
        for(int i = 0; i < list.size() - 1; i++){
            for(int j = i + 1; j < list.size(); j++){
                Record firstRecord = list.get(i);
                Record secondRecord = list.get(j);
                long firstTotalCount = Long.parseLong(firstRecord.get("total_count").toString());
                long secondTotalCount = Long.parseLong(secondRecord.get("total_count").toString());
                if(firstTotalCount < secondTotalCount){
                    list.set(i, secondRecord);
                    list.set(j, firstRecord);
                }
            }
        }
        return list;
    }

    private void outputToFile(List<Record> list, OutputStreamWriter osr) throws IOException{
        for(int i = 0; i < list.size(); i++){
            Record item = list.get(i);
            osr.write(convertRecordToString(item));
            osr.write("\r\n");
        }
    }

    private void closeWriter(OutputStreamWriter osr){
        if(osr != null){
            try{
                osr.close();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public void exportAndUpload(){
        try{
            DsLog.log(params.logTag + " 导出开始：" + params.toString());
            CmccFtpUtil ftpUtils = getCmccFtpUtil(ftpParam);
            String filePath = exportDataByParams(params);
            // saveExportResult(params, filePath);
            // upload(params, params.logTag, ftpUtils, filePath);
        }
        catch(IOException e){
            e.printStackTrace();
        }
    }

    private CmccFtpUtil getCmccFtpUtil(FtpParam ftpParam){
        return new CmccFtpUtil(ftpParam.host, ftpParam.port, ftpParam.account, ftpParam.password, ftpParam.encoding,
                ftpParam.remotePath);
    }

    private void upload(SyncParams params, String type, CmccFtpUtil ftpUtils, String filePath)
            throws FileNotFoundException, IOException{
        FileInputStream fis;
        fis = new FileInputStream(filePath);
        DsLog.log(type + " 数据上传FTP服务器：" + params.toString() + ":" + ftpUtils.getServerIp() + ":" + filePath + ". size="
                + fis.available());
        ftpUtils.uploadFile(getFileName(params), fis);
        fis.close();
        DsLog.log(type + " 数据上传深圳服务器完成：" + params.toString());
    }

    private String getSalesUniqueSql(ConcurrentHashMap<String, String> searchInfo, List<String> business_code){
        StringBuffer sql = new StringBuffer(" SELECT COUNT(*) AS total_count,sp.userId,m.user_name,oc.DisplayName");
        sql.append(" FROM (SELECT * FROM (SELECT * FROM sales_promotion WHERE 1=1 AND  isDelete=0 ");
        if(searchInfo.containsKey("start")){
            sql.append(" AND  time  >= '" + searchInfo.get("start").replaceAll(" ", "") + " 00:00:00'");
        }
        if(searchInfo.containsKey("end")){
            sql.append(" AND  time <= '" + searchInfo.get("end").replaceAll(" ", "") + " 23:59:59'");
        }
        if(ObjectUtil.isNotEmpty(business_code) && business_code.size() > 0){
            String business_code_str = "";
            for(String business_code_val : business_code){
                if(business_code_str.length() > 0){
                    business_code_str += ",";
                }
                business_code_str += "'" + business_code_val + "'";
            }
            sql.append(" AND business_code in(").append(business_code_str).append(")");
        }
        sql.append("  AND moduleId=4");
        sql.append("  AND business_code !='4001' ");
        sql.append("  AND business_code !='1895' ");
        sql.append("  ORDER BY time DESC)AS a  GROUP BY phone_no)AS sp ");
        sql.append(" LEFT JOIN member_org m ON sp.userid = m.id  ");
        sql.append(" LEFT JOIN organization o ON m.org_id = o.id   ");
        sql.append(" LEFT JOIN organization oc ON oc.id = o.CityCode   ");
        sql.append(" GROUP BY userid  ORDER BY total_count DESC ");
        return sql.toString();
    }

    private String getSalesOtherSql(ConcurrentHashMap<String, String> searchInfo, List<String> business_code){
        StringBuffer sql = new StringBuffer(" SELECT COUNT(*) AS total_count,sp.userId,m.user_name,oc.DisplayName");
        sql.append(" FROM sales_promotion sp  ");
        sql.append(" LEFT JOIN member_org m ON sp.userid = m.id  ");
        sql.append(" LEFT JOIN organization o ON m.org_id = o.id   ");
        sql.append(" LEFT JOIN organization oc ON oc.id = o.CityCode  WHERE 1=1 AND sp.isDelete=0 ");
        sql.append("  AND sp.business_code !='4001' ");
        sql.append("  AND sp.business_code !='1895' ");
        if(searchInfo.containsKey("start")){
            sql.append(" AND  sp.time  >= '" + searchInfo.get("start").replaceAll(" ", "") + " 00:00:00'");
        }
        if(searchInfo.containsKey("end")){
            sql.append(" AND   sp.time <= '" + searchInfo.get("end").replaceAll(" ", "") + " 23:59:59'");
        }

        if(ObjectUtil.isNotEmpty(business_code) && business_code.size() > 0){
            String business_code_str = "";
            for(String business_code_val : business_code){
                if(business_code_str.length() > 0){
                    business_code_str += ",";
                }
                business_code_str += "'" + business_code_val + "'";
            }
            sql.append(" AND (sp.business_code not in(").append(business_code_str).append(")");
        }
        sql.append("  OR sp.moduleId !=4)");
        sql.append(" GROUP BY sp.userid  ORDER BY total_count DESC ");
        return sql.toString();
    }

    private String getReservationSql(ConcurrentHashMap<String, String> searchInfo){
        StringBuffer sql = new StringBuffer(" SELECT COUNT(*) AS total_count,"
                + "sr.user_id AS userId,sr.city AS DisplayName,m.user_name AS user_name  ");
        sql.append(" FROM service_reservation sr");
        sql.append(" LEFT JOIN member_org m ON sr.user_id = m.id WHERE 1=1  AND sr.is_deleted=0  ");
        if(searchInfo.containsKey("start")){
            sql.append(" AND  sr.create_date >= '" + searchInfo.get("start").replaceAll(" ", "") + " 00:00:00'");
        }
        if(searchInfo.containsKey("end")){
            sql.append(" AND  sr.create_date <= '" + searchInfo.get("end").replaceAll(" ", "") + " 23:59:59'");
        }
        sql.append(" GROUP BY sr.user_id");
        return sql.toString();
    }

    public static void main(String[] args){
        List<Integer> list = new ArrayList<>();
        list.add(6);
        list.add(21);
        list.add(3);
        list.add(8);
        list.add(9);
        list.add(19);
        list.add(5);
        for(int i = 0; i < list.size() - 1; i++){
            for(int j = i + 1; j < list.size(); j++){
                int first = list.get(i);
                int second = list.get(j);
                if(first < second){
                    list.set(i, second);
                    list.set(j, first);
                }
            }
        }
        for(Integer integer : list){
            logger.debug(integer + "");
        }
    }

}
